package test.progenies.ecg.asm31.methods;

import static org.junit.Assert.assertNotNull;

import org.junit.Before;

import com.progenies.ecg.generator.ClassGenerator;
import com.progenies.ecg.generator.ClassGeneratorFactory;
import com.progenies.ecg.model.ClassObject;
import com.progenies.ecg.model.ConstructorObject;
import com.progenies.ecg.model.codeparts.lines.LineFactory;

public abstract class BaseTestExternalLocalMethods {

	protected ClassGenerator clsGenerator;
	private static int counter = 0;

	@Before
	public void setUp() throws Exception {
		clsGenerator=ClassGeneratorFactory.getClassGenerator();
		assertNotNull(clsGenerator);
	}

	protected ClassObject createClass() {
		counter++;
		int index=counter;
		LineFactory lineFactory=clsGenerator.lineFactory;
		String subpackage=this.getClass().getPackage().getName().substring(this.getClass().getPackage().getName().lastIndexOf('.')+1);
		ClassObject cls=clsGenerator.objectFactory.classes.createClass("test."+subpackage+".ExternalLocalMethodTestClass"+index);
		cls.setSuperClass(Object.class);
		
		cls.getFields().add(clsGenerator.objectFactory.fields.createField("value", int.class));
		
		
		//override default constructor
		ConstructorObject consObject=clsGenerator.objectFactory.constructors.createConstructor();
		consObject.setCode(lineFactory.methods.invokeSuperConstructor());
		cls.getConstructors().add(consObject);
	
				
		return cls;
	}

	public static final class MethodClass
	{
		protected int value;
		
		public int methodCheck()
		{
			return value;
		}
		
		public void testVoid()
		{
			value++;
			return;
		}
		
		public int testInt()
		{
			return 5;
		}
		
		public double testDouble()
		{
			return 7d;
		}
		
		public ValueObject testValueObject(int params[])
		{
			if(params==null)
				return null;
			
			int tmp=0;
			for(int i=0;i<params.length;i++)
			{
				tmp+=params[i];
			}
			return testValueObject(tmp);
		}
		
		public ValueObject testValueObject(ValueObject params[])
		{
			if(params==null)
				return null;
			
			int tmp=0;
			for(int i=0;i<params.length;i++)
			{
				tmp+=params[i].internalValue;
			}
			return testValueObject(tmp);
		}
		
		public ValueObject testValueObject(int param)
		{
			return param>0?new ValueObject(param):null;
		}
		
		public ExtendedValueObject testExtendedValueObject(int param)
		{
			return param>0?new ExtendedValueObject(param):null;
		}
		
		public ValueIface testIfaceValueObject(int param)
		{
			return param>0?new ValueObject(param):null;
		}
		
		public void setValueObject(ValueObject param)
		{
			this.value=param.getInternalValue();
		}
		
		public void setValue(int param)
		{
			this.value=param;
		}
		
		
	}

	public interface ValueIface
	{
		public int getInternalValue();
	}

	public static class ValueObject implements ValueIface
	{
		public int internalValue;
		
		public ValueObject(int v)
		{
			this.internalValue=v;
		}
		
		
		public int getInternalValue()
		{
			return internalValue;
		}
	}

	public static class ExtendedValueObject extends ValueObject
	{
		public ExtendedValueObject(int val)
		{
			super(val*2);
		}
	}

}
